package com.dz.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.dz.constant.MessageConstant;
import com.dz.constant.PageConstant;
import com.dz.constant.StatusConstant;
import com.dz.dto.SetmealDTO;
import com.dz.dto.SetmealPageQueryDTO;
import com.dz.entity.Dish;
import com.dz.entity.SetMeal;
import com.dz.entity.SetmealDish;
import com.dz.enumeration.AppHttpCodeEnum;
import com.dz.exception.SystemException;
import com.dz.mapper.SetMealMapper;
import com.dz.mapper.SetmealDishMapper;
import com.dz.result.Result;
import com.dz.service.SetmealService;
import com.dz.utils.BeanCopyUtils;
import com.dz.vo.DishItemVO;
import com.dz.vo.PageVo;
import com.dz.vo.SetmealPageVo;
import com.dz.vo.SetmealVO;
import io.jsonwebtoken.lang.Assert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Objects;

/**
 * @author 鄧浩奇
 * @classname SetmealServiceImpl
 * @description
 * @since 2023/12/28 19:38
 **/

@Service
public class SetmealServiceImpl implements SetmealService {

    private final SetMealMapper setMealMapper;

    private final SetmealDishMapper setmealDishMapper;

    @Autowired
    public SetmealServiceImpl(SetMealMapper setMealMapper, SetmealDishMapper setmealDishMapper) {
        this.setMealMapper = setMealMapper;
        this.setmealDishMapper = setmealDishMapper;
    }


    /*
     * 新增套餐
     * */
    @Transactional
    @Override
    public Result<String> insertSetmeal(SetmealDTO setmealDTO) {
        checkSetmealDto(setmealDTO);
        // 写入套餐信息
        SetMeal setMeal = BeanCopyUtils.copyBean(setmealDTO, SetMeal.class);
        Integer insertSetmeal = setMealMapper.insertSetmeal(setMeal);
        if (insertSetmeal.equals(StatusConstant.INSERT_ERROR)) throw new SystemException(AppHttpCodeEnum.INSERT_ERROR);
        // 写入套餐所包含的菜品
        List<SetmealDish> setmealDishes = setmealDTO.getSetmealDishes();
        setmealDishes.forEach(setmealDish -> setmealDish.setSetmealId(setMeal.getId()));
        Integer insertSetMailDish = setMealMapper.insertSetmailDishBatch(setmealDishes);
        if (insertSetMailDish.equals(StatusConstant.INSERT_ERROR))
            throw new SystemException(AppHttpCodeEnum.INSERT_ERROR);
        return Result.success();

    }

    /*
     * 套餐分页
     * */
    @Override
    public PageVo page(SetmealPageQueryDTO queryDTO) {
        if (queryDTO.getPage() < PageConstant.MIN_PAGE_NUM || queryDTO.getPageSize() < PageConstant.MIN_PAGE_NUM)
            throw new SystemException(AppHttpCodeEnum.ERROR_PAGE);
        PageHelper.startPage(queryDTO.getPage(), queryDTO.getPageSize());
        Page<SetmealPageVo> pages = setMealMapper.getPage(queryDTO);
        return new PageVo(pages.getResult(), pages.getTotal());
    }

    /*
     * 根据id查询
     * */
    @Override
    public SetmealVO getById(Long id) {
        // 查询套餐
        SetmealVO setmealVO = setMealMapper.selectById(id);
        Assert.notNull(setmealVO, AppHttpCodeEnum.SYSTEM_ERROR.getMsg());
        // 根据setmeal_id查询套餐包含的菜品集合
        List<SetmealDish> list = setMealMapper.selectListById(id);
        setmealVO.setSetmealDishes(list);
        return setmealVO;
    }

    /*
     * 修改套餐
     * */
    @Transactional
    @Override
    public Result<String> update(SetmealDTO setmealDTO) {
        checkSetmealDto(setmealDTO);
        // 更新 套餐
        SetMeal setMeal = BeanCopyUtils.copyBean(setmealDTO, SetMeal.class);
        Integer updateSetmeal = setMealMapper.update(setMeal);
        if (updateSetmeal.equals(StatusConstant.UPDATE_ERROR)) throw new SystemException(AppHttpCodeEnum.UPDATE_ERROR);
        // 删除套餐原来包含的菜品
        Integer delete = setMealMapper.deleteSetmealDishBySetmealId(setmealDTO.getId());
        if (delete.equals(StatusConstant.UPDATE_ERROR)) throw new SystemException(AppHttpCodeEnum.DELETE_ERROR);
        // 更新套餐包含的菜品
        List<SetmealDish> setmealDishes = setmealDTO.getSetmealDishes();
        setmealDishes.forEach(setmealDish -> setmealDish.setSetmealId(setmealDTO.getId()));
        Integer updateSetmealDishBatch = setMealMapper.insertSetmailDishBatch(setmealDishes);
        if (updateSetmealDishBatch.equals(StatusConstant.UPDATE_ERROR))
            throw new SystemException(AppHttpCodeEnum.UPDATE_ERROR);
        return Result.success();
    }


    /*
     * 批量删除
     * */
    @Transactional
    @Override
    public Result<String> deleteBatch(List<Long> ids) {
        Assert.notEmpty(ids, AppHttpCodeEnum.SETMEAL_DISH_IS_NULL.getMsg());
        // 判断 被删除套餐是否是起售状态
        List<Long> canDeleteIdList = ids.stream().filter(id -> setMealMapper.selectById(id).getStatus().equals(StatusConstant.DISABLE)).toList();
        // 起售状态的套餐无法删除
        if (canDeleteIdList.isEmpty()) return Result.error(MessageConstant.SETMEAL_ON_SALE);
        // 删除套餐
        Integer delSetmeal = setMealMapper.deleteBatch(canDeleteIdList);
        if (delSetmeal.equals(StatusConstant.DELETE_ERROR)) throw new SystemException(AppHttpCodeEnum.DELETE_ERROR);
        // 删除套餐下的菜品
        canDeleteIdList.forEach(setMealMapper::deleteSetmealDishBySetmealId);
        if (!canDeleteIdList.equals(ids))
            // 仅删除了能未起售的套餐
            return Result.error(MessageConstant.SETMEAL_ON_SALE_ONLY_DEL_PART);
        else
            return Result.success();
    }


    /*
     * 修改套餐状态 0:停用 1:启用
     * */
    @Override
    public Result<String> changeStatus(Long id, Integer status) {
        // 参数校验
        Assert.notNull(id, AppHttpCodeEnum.ID_ERROR.getMsg());
        Assert.notNull(status, AppHttpCodeEnum.status_ERROR.getMsg());
        SetMeal setMeal = SetMeal.builder()
                .id(id)
                .status(status)
                .build();
        switch (status) {
            case 0 -> setMealMapper.updateStatus(setMeal); // 当前状态是 1启用，需要改为停售

            case 1 -> {
                // 当前状态是 0停售，需要改为起售
                // 改为起售状态需要判断包含的菜品是否有停售的

                // 查询该id套餐下的所有菜品
                List<Dish> dishes = setmealDishMapper.selectDishById(id);
                List<Dish> list = dishes.stream().filter(dish -> dish.getStatus().equals(StatusConstant.DISABLE)).toList();
                if (list.isEmpty()) {
                    // 包含的菜品都是起售状态，可以起售套餐
                    setMealMapper.updateStatus(setMeal);
                } else return Result.error(MessageConstant.SETMEAL_ENABLE_FAILED);
            }
            default -> throw new SystemException(AppHttpCodeEnum.DATA_ERROR);
        }
        return Result.success();
    }


    /*
    * 根据分类id查询套餐信息
    * */
    @Override
    public List<SetMeal> getListByCategoryId(Long categoryId) {
        List<SetMeal> setMeals = setMealMapper.selectByCategoryId(categoryId);
        if (Objects.isNull(setMeals)) {
            throw new SystemException(AppHttpCodeEnum.SYSTEM_ERROR);
        }
        return setMeals;
    }


    @Override
    public List<DishItemVO> getDishBySetmealId(Long setmealId) {
        List<DishItemVO> dishItemVOList = setmealDishMapper.selectDishBySetmealId(setmealId);
        if (Objects.isNull(dishItemVOList)) {
            throw new SystemException(AppHttpCodeEnum.SYSTEM_ERROR);
        }
        return dishItemVOList;
    }

    /*
     * 校验 SetmealDTO 中的属性
     * */
    private void checkSetmealDto(SetmealDTO setmealDTO) {
        Assert.notNull(setmealDTO.getCategoryId(), AppHttpCodeEnum.CATEGORY_ID_IS_NULL.getMsg());
        Assert.isTrue(StringUtils.hasText(setmealDTO.getImage()), AppHttpCodeEnum.IMAGE_ADDRESS_IS_NULL.getMsg());
        Assert.isTrue(StringUtils.hasText(setmealDTO.getName()), AppHttpCodeEnum.SETMEAL_NAME_IS_NULL.getMsg());
        Assert.notNull(setmealDTO.getPrice(), AppHttpCodeEnum.PRICE_IS_NULL.getMsg());
        Assert.notNull(setmealDTO.getStatus(), AppHttpCodeEnum.STATUS_IS_NULL.getMsg());
        Assert.notEmpty(setmealDTO.getSetmealDishes(), AppHttpCodeEnum.SETMEAL_DISH_IS_NULL.getMsg());
    }
}
